package main

import (
	"fmt"
	"math/rand"
	"sort"
	"time"
)

func main() {
	//作业1
	s1 := make([]int, 3, 4) //元素[0 0 0]	底层数组[0 0 0]
	s2 := append(s1, 1)     //元素[0 0 0 1]	底层数组[0 0 0 1]
	fmt.Printf("%T %[1]v %[3]p\t %[2]T %[2]v %[4]p\n", s1, s2, &s1[0], &s2[0])
	s1[1] = 4
	fmt.Printf("%T %[1]v %[3]p\t %[2]T %[2]v %[4]p\n", s1, s2, &s1[0], &s2[0]) //修改s1的一个元素会影响到s2，s1和s2共用底层数组[0 4 0 1]

	s2[3] = 100
	fmt.Printf("%T %[1]v %[3]p\t %[2]T %[2]v %[4]p\n", s1, s2, &s1[0], &s2[0]) //修改s2的最后一个元素，不会影响到s1，s1和s2共用底层数组[0 4 0 100]
	s2[0] = 1000
	fmt.Printf("%T %[1]v %[3]p\t %[2]T %[2]v %[4]p\n", s1, s2, &s1[0], &s2[0]) //修改s2的非最后一个元素，会影响到s1，s1和s2共用底层数组[1000 4 0 100]

	s2 = append(s2, 5)
	fmt.Printf("%T %[1]v %[3]p\t %[2]T %[2]v %[4]p\n", s1, s2, &s1, &s2) //s2再增加一个元素时，会引发扩容，s2底层数组会发生变化，变为[1000 4 0 100 5]，与s1（[1000 4 0 100]）不再使用同一个底层数组

	fmt.Println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")

	//作业2
	arr := [...]int{1, 4, 9, 16, 2, 5, 10, 15}
	slice := make([]int, 0, len(arr)-1)

	fmt.Printf("the array info is:%T %[1]v len:%[2]d cap:%[3]d\n", arr, len(arr), cap(arr))
	fmt.Printf("the slice info is:%T %[1]v len:%[2]d cap:%[3]d\n", slice, len(slice), cap(slice))
	fmt.Println()
	for i := 0; i < len(arr)-1; i++ {
		start := arr[i]
		end := arr[i+1]
		slice = append(slice, start+end)
		fmt.Printf("the slice data is:%v \n", slice)
		fmt.Printf("the pointer of base array is:%p\n", &slice[0])
	}
	fmt.Println()
	fmt.Printf("%v len:%[2]d cap:%[3]d %[4]p\n", slice, len(slice), cap(slice), &slice[0])

	fmt.Println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")

	//作业3
	var length, offset, num, total int = 201, 100, 100, 0
	//创建map，并初始化
	//var intMap map[int]int可以定义但是无法直接写入元素并使用
	//直接使用会报assignment to entry in nil map的panic，必须使用make进行初始化后才能使用
	intMap := make(map[int]int)
	//创建rand源
	src := rand.NewSource(time.Now().UnixNano())
	//创建rand的随机数生成器
	gen := rand.New(src)
	for i := 0; i < num; i++ {
		//生成随机数，范围是：[0,length),后面跟上offset可以控制生成不同范围的随机数
		randNum := gen.Intn(length) - offset
		_, ok := intMap[randNum]
		if ok {
			intMap[randNum] += 1
		} else {
			intMap[randNum] = 1
		}
	}
	fmt.Printf("the sort map data is:%v len:%d\n", intMap, len(intMap))
	//由于map是无序的，所以要对map排序必须先对map的key进行排序
	//使用slice对map的key进行排序
	intSlice := make([]int, 0, len(intMap))
	fmt.Printf("the sort slice info is:%v %d %d\n", intSlice, len(intSlice), cap(intSlice))
	fmt.Println()
	for i, _ := range intMap {
		intSlice = append(intSlice, i)
	}

	//判断slice是否已经进行了排序
	// flag := sort.IntsAreSorted(intSlice)
	flag := sort.SliceIsSorted(intSlice, func(i, j int) bool {
		return intSlice[i] > intSlice[j]
	})
	fmt.Printf("the sorted flag is:%t\n", flag)
	fmt.Println()
	if !flag {
		//使用int格式的默认升序排序
		// sort.Ints(intSlice1)
		//使用slice的自定义排序，可以惊醒升序/降序排序
		sort.Slice(intSlice, func(i, j int) bool {
			return intSlice[i] > intSlice[j]
		})

	}

	//打印结构
	for _, v := range intSlice {
		total += intMap[v]
		fmt.Printf("the number %d count is : %v\n", v, intMap[v])
	}
	fmt.Printf("the gen number count is:%d\n", total)
}

// 批改意见
// 1. 思路清晰，逻辑正确，可以尝试把每个题目抽取到单独的函数中实现